/**
 * Copyright 2019 吉鼎科技.

 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cn.easyplatform.services.project;

import cn.easyplatform.cfg.EngineConfiguration;
import cn.easyplatform.entities.beans.ResourceBean;
import cn.easyplatform.messages.vos.admin.ResourceVo;
import cn.easyplatform.services.IScheduleHandler;
import cn.easyplatform.services.IScheduleService;
import cn.easyplatform.type.EntityType;
import cn.easyplatform.type.StateType;
import cn.easyplatform.type.SubType;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;


/**
 * @author <a href="mailto:davidchen@epclouds.com">littleDog</a> <br/>
 * @since 2.0.0 <br/>
 */
class ScheduleHandlerImpl implements IScheduleHandler {

    // 自定义的job
    private List<String> jobWorkers;

    private ProjectService ps;

    // 计划任务服务
    private IScheduleService sched;

    private Lock lock = new ReentrantLock();

    ScheduleHandlerImpl(EngineConfiguration engineConfiguration,
                        ProjectService ps) {
        this.ps = ps;
        jobWorkers = new ArrayList<String>();
        sched = engineConfiguration.getScheduleService();
    }

    @Override
    public Map<String, Object> start(ResourceBean bean) {
        lock.lock();
        try {
            sched.stop(ps.getId(), bean.getId());
            jobWorkers.remove(bean.getId());
            sched.start(ps, bean);
            jobWorkers.add(bean.getId());
            return sched.getRuntimeInfo(ps.getId(), bean.getId());
        } finally {
            lock.unlock();
        }
    }

    @Override
    public void stop(String id) {
        lock.lock();
        try {
            sched.stop(ps.getId(), id);
            jobWorkers.remove(id);
        } finally {
            lock.unlock();
        }
    }

    @Override
    public Map<String, Object> pause(String id) {
        sched.pause(ps.getId(), id);
        return sched.getRuntimeInfo(ps.getId(), id);
    }

    @Override
    public Map<String, Object> resume(String id) {
        sched.resume(ps.getId(), id);
        return sched.getRuntimeInfo(ps.getId(), id);
    }

    @Override
    public List<ResourceVo> getServices() {
        List<ResourceBean> jobEntities = ps.getEntityHandler().getEntities(EntityType.RESOURCE.getName(), SubType.JOB.getName());
        lock.lock();
        try {
            List<ResourceVo> services = new ArrayList<>();
            List<String> tmp = new ArrayList<String>(jobWorkers);
            for (ResourceBean rb : jobEntities) {
                ResourceVo rv = new ResourceVo(rb.getId(), rb.getName(), rb.getProps());
                rv.setType(rb.getType());
                rv.setSubType(rb.getSubType());
                if (tmp.contains(rb.getId())) {
                    tmp.remove(rb.getId());
                    rv.setRuntimeInfo(sched.getRuntimeInfo(ps.getId(), rb.getId()));
                    rv.setState(sched.getState(ps.getId(), rb.getId()));
                } else
                    rv.setState(StateType.STOP);
                services.add(rv);
            }
            if (!tmp.isEmpty()) {
                for (String id : tmp) {
                    sched.stop(ps.getId(), id);
                    jobWorkers.remove(id);
                }
            }
            return services;
        } finally {
            lock.unlock();
        }
    }

    @Override
    public void pauseAll() {
        sched.pauseGroup(ps.getId());
    }

    @Override
    public void resumeAll() {
        sched.resumeGroup(ps.getId());
    }

    @Override
    public Map<String, Object> getRuntimeInfo() {
        if (jobWorkers.isEmpty())
            return null;
        Map<String, Object> info = new HashMap<>();
        int activeCount = 0;
        for (String id : jobWorkers) {
            int state = sched.getState(ps.getId(), id);
            if (state == StateType.START)
                activeCount++;
        }
        info.put("ActiveCount", activeCount);
        info.put("MaxCount", jobWorkers.size());
        return info;
    }

    void destory() {
        sched.stopGroup(ps.getId());
        jobWorkers.clear();
    }

}
